<?php

/**
 * Фильтр структуры фронтенда. Определяет активный пункт меню.
 *
 */
class Kernel_Filter_Structure extends Kernel_Filter {

    /**
     * Пункт меню, соответствующий текущим параметра запуска приложения.
     *
     * @var integer
     */
    static private $_id;

    /**
     * Запускает фильтр
     *
     */
    public function process() {

        parent::process();

        // ищем пункт меню, соответствеющий параметрам запуска приложения
        $id = $this->_getActiveElement();

        if (empty($id)) {
            $this->_abort('Resource not found');
        }

        // сохраняем результат
        self::$_id = $id;
    }

    /**
     * Возвращает пункт меню, соответствующий текущим параметра запуска
     * приложения.
     *
     * @return  integer
     */
    static public function getMenuId() {
        return self::$_id;
    }

    /**
     * Определяет пункт меню, соответствующий текущиму URL.
     *
     * @param   array   $params
     * @return  integer
     */
    private function _getActiveElement() {

        $uri = Application::getRequest()->uri();

        // если параметры не указаны
        if (empty($uri)) {

            // пытаемся найти ресурс, соответствующий корню сайта
            $id = self::_findActiveElement('');

            // если такого нету
            if (empty($id)) {

                // определяем пункт меню по умолчанию
                if (strlen($uri = $this->_getDefaultUrl()) > 0) {

                    // перенаправляем агента с явным указанием URL'а, чтобы не
                    // дублировать одно содержимое на страницах с разными URL'ами
                    $this->_location($uri, true);
                }
            }
            return $id;
        } else {
            for ($size = count($uri); $size > 0; $size--) {
                $slice = implode('/', array_slice($uri, 0, $size)) . '/';
                if (($id = self::_findActiveElement($slice)) > 0) {
                    // обрубаем параметры, оставляя только неиспользованные
                    // куски пути. по идее, ресурс в своем описании должен
                    // содержать все необходимые параметры
                    // $params = array_slice($params, $size);
                    return $id;
                }
            }
        }

        return false;
    }

    /**
     * Ищет пункт меню, соответствующий указанному фрагменту URL.
     *
     * @param   string  $url
     * @return  integer
     */
    private function _findActiveElement($url) {
        $query = 'SELECT
                         `id`
                    FROM
                         `system_resource`
                   WHERE
                         `url` = "' . database::escape($url) . '"';
        return database::fetchOne($query);
    }

    /**
     * Определяет URL элемента структуры по умолчанию - того, на который
     * ссылается первый пункт основного меню навигации.
     *
     * @return  string
     */
    private function _getDefaultUrl() {
        $query = 'SELECT
                         `r`.`url`
                    FROM
                         `system_navigation` `n`
              INNER JOIN
                         `system_navigation_item` `i`
                      ON
                         `i`.`menu_id` = `n`.`id`
                     AND
                         `i`.`parent_id` = 0
              INNER JOIN
                         `system_resource` `r`
                      ON
                         `r`.`id` = `i`.`resource_id`
                ORDER BY
                         -- основное меню навигации
                         `n`.`id`,

                         -- первый пункт меню
                         `i`.`position`
                   LIMIT
                         1';

        return database::fetchOne($query);
    }
}
